﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace DataService.Core.Encrypt
{
    public class RSAHelper
    {
        /// <summary>
        /// 返回公钥和私钥
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, string> GetPrivateAndpublic()
        {
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                #region 生成xml文件
                //using (StreamWriter writer = new StreamWriter("PrivateKey.xml"))
                //{
                //    writer.WriteLine(rsa.ToXmlString(true));
                //}
                //using (StreamWriter writer = new StreamWriter("PublicKey.xml"))
                //{
                //    writer.WriteLine(rsa.ToXmlString(false));
                //}
                #endregion
                Dictionary<string, string> dic = new Dictionary<string, string>();
                byte[] PrivateBuffer = System.Text.Encoding.UTF8.GetBytes(rsa.ToXmlString(true));
                byte[] publicBuffer = System.Text.Encoding.UTF8.GetBytes(rsa.ToXmlString(false));
                dic["PrivateKey"] = Convert.ToBase64String(PrivateBuffer);
                dic["publicKey"] = Convert.ToBase64String(publicBuffer);
                return dic;
            }

        }
        /// <summary>
        /// 加密长字符串
        /// </summary>
        /// <param name="xmlPublicKey">公钥</param>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <returns></returns>
        public static String RSAEncrypt(string xmlPublicKey, String encryptStr)
        {
            byte[] b = Convert.FromBase64String(xmlPublicKey);
            xmlPublicKey = System.Text.Encoding.UTF8.GetString(b);
            using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
            {
                provider.FromXmlString(xmlPublicKey);
                Byte[] PlaintextData = Encoding.UTF8.GetBytes(encryptStr);
                int MaxBlockSize = provider.KeySize / 8 - 11;    //加密块最大长度限制

                if (PlaintextData.Length <= MaxBlockSize)
                    return Convert.ToBase64String(provider.Encrypt(PlaintextData, false));

                using (MemoryStream PlaiStream = new MemoryStream(PlaintextData))
                using (MemoryStream CrypStream = new MemoryStream())
                {
                    Byte[] Buffer = new Byte[MaxBlockSize];
                    int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        Byte[] ToEncrypt = new Byte[BlockSize];
                        Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);

                        Byte[] Cryptograph = provider.Encrypt(ToEncrypt, false);
                        CrypStream.Write(Cryptograph, 0, Cryptograph.Length);

                        BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }

                    return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
                }
            }
        }
        /// <summary>
        /// 解密长字符串
        /// </summary>
        /// <param name="xmlPrivateKey">私钥</param>
        /// <param name="ciphertext">需要解密字符串</param>
        /// <returns></returns>
        public static String RSADecrypt(string xmlPrivateKey, String decryptStr)
        {
            byte[] b = Convert.FromBase64String(xmlPrivateKey);
            xmlPrivateKey = System.Text.Encoding.UTF8.GetString(b);
            using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
            {
                provider.FromXmlString(xmlPrivateKey);
                Byte[] CiphertextData = Convert.FromBase64String(decryptStr);
                int MaxBlockSize = provider.KeySize / 8;    //解密块最大长度限制

                if (CiphertextData.Length <= MaxBlockSize)
                    return Encoding.UTF8.GetString(provider.Decrypt(CiphertextData, false));

                using (MemoryStream CrypStream = new MemoryStream(CiphertextData))
                {
                    using (MemoryStream PlaiStream = new MemoryStream())
                    {
                        Byte[] Buffer = new Byte[MaxBlockSize];
                        int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);

                        while (BlockSize > 0)
                        {
                            Byte[] ToDecrypt = new Byte[BlockSize];
                            Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);

                            Byte[] Plaintext = provider.Decrypt(ToDecrypt, false);
                            PlaiStream.Write(Plaintext, 0, Plaintext.Length);

                            BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
                        }

                        return Encoding.UTF8.GetString(PlaiStream.ToArray());
                    }
                }

            }
        }
    }
}
